package com.softtek.history;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import java.util.Set;

import com.softtek.webbrowser.JBProperties;


/**
 * Controls URL history storage
 * @author hector.nevarez
 *
 */
public class History implements Observer{
	
	private File historyFile;
	private Set<String> persistentHistory;
	private List<String> sessionHistory;
	
	private Integer currentUrl;
	private Boolean historyEnabled = true;
	
	/**
	 * Class constructor
	 */
	public History(){
		String historyFilePath = JBProperties.getProperties().getProperty("HISTORY_FILE");
		historyFile = new File( historyFilePath );
		
		persistentHistory = new LinkedHashSet<String>();
		sessionHistory = new LinkedList<String>();
		
		getHistoryFromFile();
	}
	
	/**
	 * Updates the session history
	 * @param url
	 */
	protected void updateSessionHistory(final String url){
		if(historyEnabled){	
			sessionHistory.add(url);
			currentUrl = sessionHistory.size() - 1;
		}
	}
	/**
	 * Sets is history is set to register URLManager change events
	 * this is used for not registering url changes when navigating history (back and forward)
	 * @param enableHistoryLogging
	 */
	public void registerHistory(final Boolean enableHistoryLogging){
		historyEnabled = enableHistoryLogging;
	}
	/**
	 * Returns the current URL
	 * @return
	 */
	public String getCurrentUrl(){
		return sessionHistory.get(currentUrl);
	}
	/**
	 * Return previous url in session history
	 * @return
	 */
	public String back(){
		String backUrl = null;
		if( currentUrl != null){
			if( (currentUrl -1) >= 0 && (currentUrl -1) <= sessionHistory.size()-1  ){
				backUrl = sessionHistory.get(currentUrl -1);
				currentUrl--;
			}
		}
				
		return backUrl;
	}
	/**
	 * Returns next url in session history list
	 * @return
	 */
	public String forward(){
		String forwardUrl = null;
		if( currentUrl != null){
			if( (currentUrl +1) <= sessionHistory.size()-1  ){
				currentUrl++;
				forwardUrl = sessionHistory.get(currentUrl);
			}
		}
		
		return forwardUrl;
	}
	
	/**
	 * Locally stores the current session history in the 
	 * HISTORY_FILE (specified in the browser.properties file)
	 */
	public void persist(){
		
		BufferedWriter historyWriter = null;
		
		try{
			try{
				
			    historyWriter = new BufferedWriter( new FileWriter(historyFile, true) );
				
			    for(Iterator<String> urlAddress = sessionHistory.iterator();  urlAddress.hasNext(); ){
			    	String urlAddressStr = urlAddress.next();
			    	if(!urlAddressStr.isEmpty() && persistentHistory.add(urlAddressStr)){
				    	historyWriter.append(urlAddressStr);
				    	historyWriter.newLine();
			    	}
			    }
				
				historyWriter.flush(); 
				
			}catch(IOException ioe){
				//Error writing File
			}finally{
				historyWriter.close();
			}
		}catch(IOException ioe){
			//Error closing history writer stream;
		}
	}
	/**
	 * Retrieves the history stored in the HISTORY_FILE 
	 * (specified in the browser.properties file)
	 * 
	 * @return string containing the HISTORY_FILE content
	 * @throws IOException
	 */
	public void getHistoryFromFile(){
		try{	
			final BufferedReader historyReader = new BufferedReader(new FileReader(historyFile));
		
			String line = null;
		
		
			while( (line = historyReader.readLine()) != null){
				persistentHistory.add(line);
			}
		}catch(IOException ioe){
		}
	}
	/**
	 * 
	 * @return
	 */
	public Set<String> getHistoryList(){
		Set<String> currentList = new LinkedHashSet<String>(persistentHistory);
		
		for(Iterator<String> urlAddress = sessionHistory.iterator();  urlAddress.hasNext(); ){
	    	String urlAddressStr = urlAddress.next();
	    	if(!urlAddressStr.isEmpty()){
	    		currentList.add( urlAddressStr );
	    	}
	    }
		
		return currentList;
	}
	/**
	 * Updates the history every time the URLManager {@link URLManager} 
	 * successfully opens a URL.
	 */
	public void update(Observable ob, Object urlObj){
		String URL = (String) urlObj;
		updateSessionHistory(URL);
	}
}
